%File: ~/OOP/system_of_eqn/linearSOE/sparseGen/SparseGenColLinSOE.tex
%What: "@(#) SparseGenColLinSOE.tex, revA"

\noindent {\bf Files}   \\
\indent \#include $<\tilde{ }$/system\_of\_eqn/linearSOE/sparseGen/SparseGenColLinSOE.h$>$  \\

\noindent {\bf Class Declaration}  \\
\indent class SparseGenColLinSOE: public LinearSOE \\

\noindent {\bf Class Hierarchy} \\
\indent MovableObject \\
\indent\indent SystemOfEqn \\
\indent\indent\indent LinearSOE \\
\indent\indent\indent\indent {\bf SparseGenColLinSOE} \\

\noindent {\bf Description}  \\
\indent SparseGenColLinSOE is class which is used to store the matrix
equation $Ax=b$ of order $size$ using a sparse column-compacted storage
scheme for $A$. The $A$ matrix is stored in a 1d double array with
$nnz$ elements, where $nnz$ is the number of non-zeroes in the matrix
$A$. Two additional 1d integer arrays $rowA$ and $colStartA$ are used to
store information about the location of the coefficients, with $colStartA(i)$
storing the location in the 1d double array of the start of column $i$
and $rowA(j)$ identifying the row in $A$ to which the
$j'th$ component in the 1d double array. $colStartA$ is of
dimension $size+1$ and $rowA$ of dimension $nnz$. For example

$$
\left[
\begin{array}{ccccc}
a_{0,0} & 0 & a_{0,2}  & a_{0,3} & 0  \\
a_{1,0} & a_{1,1} & 0 & 0 & 0  \\
0 & a_{2,1} & a_{2,2} & 0 & 0 \\
0 & 0 & 0 & a_{3,3} & a_{3,4} \\
a_{4,0} & a_{4,1} & 0 & 0 & a_{4,4}
\end{array}
\right] 
$$

is stored in:

$$
\left[
\begin{array}{cccccccccccccc}
a_{0,0} & a_{1,0}  & a_{4,0} & a_{1,1} & a_{2,1} & a_{4,1} &
a_{0,2} & a_{2,2} & a_{0,3} & a_{3,3} & a_{3,4} & a_{4,4}  \\
\end{array}
\right] 
$$

with

$$
colStartA =
\left[
\begin{array}{cccccccccccccc}
0 & 3 & 6 & 8 & 10 & 12
\end{array}
\right] 
$$

and

$$
rowA =
\left[
\begin{array}{cccccccccccccc}
0 & 1 & 4 & 1 & 2 & 4 & 0 & 2 & 0 & 3 & 3 & 4 
\end{array}
\right] 
$$
The $x$ and $b$ vectors are stored in 1d double arrays of length $n$. \\

\noindent {\bf Interface}  \\
\indent\indent {// Constructors} \\
\indent\indent {\em SparseGenColLinSOE(SparseGenColLinSolver \&theSolver);}  \\
\indent\indent {\em SparseGenColLinSOE(int N, int NNZ, int *colStartA,
int *rowA, SparseGenColLinSolver \&theSolver); }\\\\
\indent\indent {// Destructor} \\
\indent\indent {\em  $\tilde{}$SparseGenColLinSOE();}\\ \\
\indent\indent {// Public Methods }  \\
\indent\indent {\em  int setSparseGenSolver(SparseGenColLinSolver \&newSolver);}\\
\indent\indent {\em int setSize(const Graph \&theGraph) =0; } \\
\indent\indent {\em int getNumEqn(void) =0; } \\
\indent\indent {\em int addA(const Matrix \&theMatrix, const ID \& loc,
doublefact = 1.0) =0;} \\
\indent\indent {\em int addB(const Vector \& theVector, const ID \& loc,
double fact = 1.0) =0;} \\
\indent\indent {\em int setB(const Vector \& theVector, 
double fact = 1.0) =0;} \\
\indent\indent {\em void zeroA(void) =0;} \\
\indent\indent {\em void zeroB(void) =0;} \\
\indent\indent {\em const Vector \&getX(void) = 0;} \\
\indent\indent {\em const Vector \&getB(void) = 0;} \\
\indent\indent {\em double normRHS(void) =0;} \\
\indent\indent {\em void setX(int loc, double value) =0;}\\
\indent\indent {\em int sendSelf(int commitTag, Channel \&theChannel);}\\ 
\indent\indent {\em int recvSelf(int commitTag, Channel \&theChannel,
FEM\_ObjectBroker \&theBroker);}\\ 


\noindent {\bf Constructors}  \\
\indent {\em SparseGenColLinSOE(SparseGenColLinSolver \&solver);}  \\
The {\em solver} and a unique class tag (defined in $<$classTags.h$>$)
are passed to the LinearSOE constructor. The system size is set
to $0$ and the matrix $A$ is marked as not having been factored. Invokes
{\em setLinearSOE(*this)} on the {\em solver}. No memory is
allocated for the 3 1d arrays. \\  


{\em SparseGenColLinSOE(int N, int NNZ, int *colStartA,
int *rowA, SparseGenColLinSolver \&theSolver); }\\
The {\em solver} and a unique class tag (defined in $<$classTags.h$>$)
are passed to the LinearSOE constructor. The system size is set
to $N$, the number of non-zeros is set to $NNZ$ and the matrix $A$ is
marked as not having been factored. Obtains memory from the heap for
the 1d arrays storing the data for $A$, $x$ and $b$ and stores the
size of these arrays. If not enough memory is available for these
arrays a warning message is printed and the system size is set to
$0$. Invokes {\em setLinearSOE(*this)} and {\em setSize()} on {\em solver},
printing a warning message if {\em setSize()} returns a negative
number. Also creates Vector objects for $x$ and $b$ using the {\em
(double *,int)} Vector constructor. It is up to the user to ensure
that {\em colStartA} and {\em rowA} are of the correct size and
contain the correct data. \\

\noindent {\bf Destructor} \\
\indent {\em  $\tilde{}$SparseGenColLinSOE();}\\ 
Calls delete on any arrays created. \\

\noindent {\bf Public Methods} \\
\indent {\em  int setSolver(SparseGenColLinSolver \&newSolver);}\\
Invokes {\em setLinearSOE(*this)} on {\em newSolver}.
If the system size is not equal to $0$, it also invokes {\em setSize()}
on {\em newSolver}, printing a warning and returning $-1$ if this
method returns a number less than $0$. Finally it returns the result
of invoking the LinearSOE classes {\em setSolver()} method. \\

\indent {\em int getNumEqn(void) =0; } \\
A method which returns the current size of the system. \\

\indent {\em  int setSize(const Graph \&theGraph); } \\ 
The size of the system is determined from the Graph object {\em
theGraph}, which must contain {\em size} vertices labelled $0$ through
$size-1$, the adjacency list for each vertex containing the associated
vertices in a column of the matrix $A$. The size is determined by
invoking {\em getNumVertex()} on {\em theGraph} and the number of
non-zeros is determined by looking at the size of the adjacenecy list
of each vertex in the graph, allowing space for the diagonal term. If
the old space allocated for the 1d arrays is not big enough, it the
old space is returned to the heap and new space is allocated from the
heap. Prints a warning message, sets size to $0$ and returns a $-1$,
if not enough memory is available on the heap for the 1d arrays. If
memory is available, the components of the arrays are 
zeroed and $A$ is marked as being unfactored. If the system size has
increased, new Vector objects for $x$ and $b$ using the {\em (double
*,int)} Vector constructor are created. The $colStartA$ and $rowA$ are
then determined by looping through the vertices, setting $colStartA(i)
= colStartA(i-1) + 1 + $the size of Vertices $i$ adjacency list and 
placing the contents of $i$ and the adjacency list into $rowA$ in
ascending order. Finally, the result of invoking {\em setSize()} on
the associated Solver object is returned. \\ 


\indent {\em int addA(const Matrix \&M, const ID \& loc,
doublefact = 1.0) =0;} \\
First tests that {\em loc} and {\em M} are of compatible sizes; if not
a warning message is printed and a $-1$ is returned. The LinearSOE
object then assembles {\em fact} times the Matrix {\em 
M} into the matrix $A$. The Matrix is assembled into $A$ at the
locations given by the ID object {\em loc}, i.e. $a_{loc(i),loc(j)} +=
fact * M(i,j)$. If the location specified is outside the range,
i.e. $(-1,-1)$ the corresponding entry in {\em M} is not added to
$A$. If {\em fact} is equal to $0.0$ or $1.0$, more efficient steps
are performed. Returns $0$.  \\


{\em int addB(const Vector \& V, const ID \& loc,
double fact = 1.0) =0;} \\
First tests that {\em loc} and {\em V} are of compatible sizes; if not
a warning message is printed and a $-1$ is returned. The LinearSOE
object then assembles {\em fact} times the Vector {\em V} into
the vector $b$. The Vector is assembled into $b$ at the locations
given by the ID object {\em loc}, i.e. $b_{loc(i)} += fact * V(i)$. If a
location specified is outside the range, e.g. $-1$, the corresponding
entry in {\em V} is not added to $b$. If {\em fact} is equal to $0.0$,
$1.0$ or $-1.0$, more efficient steps are performed. Returns $0$. \\


{\em int setB(const Vector \& V, double fact = 1.0) =0;} \\
First tests that {\em V} and the size of the system are of compatible
sizes; if not a warning message is printed and a $-1$ is returned. The
LinearSOE object then sets the vector {\em b} to be {\em fact} times
the Vector {\em V}. If {\em fact} is equal to $0.0$, $1.0$ or $-1.0$,
more efficient steps are performed. Returns $0$. \\ 

{\em void zeroA(void) =0;} \\
Zeros the entries in the 1d array for $A$ and marks the system as not
having been factored. \\

{\em void zeroB(void) =0;} \\
Zeros the entries in the 1d array for $b$. \\

{\em const Vector \&getX(void) = 0;} \\
Returns the Vector object created for $x$. \\

{\em const Vector \&getB(void) = 0;} \\
Returns the Vector object created for $b$. \\

{\em double normRHS(void) =0;} \\
Returns the 2-norm of the vector $x$. \\

{\em void setX(int loc, double value) =0;}\\
If {\em loc} is within the range of $x$, sets $x(loc) = value$. \\


\indent {\em int sendSelf(int commitTag, Channel \&theChannel);}\\ 
Returns $0$. The object does not send any data or connectivity
information as this is not needed in the finite element design. \\

\indent {\em int recvSelf(int commitTag, Channel \&theChannel, FEM\_ObjectBroker
\&theBroker);}\\ 
Returns $0$. The object does not receive any data or connectivity
information as this is not needed in the finite element design.

